package main

import (
	"fmt"
	"math"
)

var globalOrLocalVar int = 100

func main() {

	// 简单函数测试-求两数最大值
	num1 := 100
	num2 := 110
	fmt.Println(max(num1, num2))

	// 函数返回多个值
	x := "tom"
	y := "jerry"
	x, y = swap_str(x, y)
	fmt.Println(x, y)

	// 值传递: 不会影响到实际参数
	a := 10
	b := 11
	fmt.Printf("交换前a=%v, b=%v \n", a, b)
	swap_val(a, b)
	fmt.Printf("交换后a=%v, b=%v \n", a, b)
	// 引用传递: 将实际参数的地址传递到函数中
	c := 100
	d := 111
	fmt.Printf("交换前c=%v, d=%v \n", c, d)
	swap_ref(&c, &d)
	fmt.Printf("交换后c=%v, d=%v \n", c, d)

	// 函数作为参数
	call_back(10, call_back_test)
	call_back(10, func(x int) int {
		fmt.Printf("自定义打印：%d \n", x)
		return x
	})

	getSquareRoot := func(x float64) float64 {
		return math.Sqrt(x)
	}
	fmt.Println(getSquareRoot(9))

	// 闭包 (匿名函数)
	// ** 函数返回另一个函数
	nextNumber := getSeq()
	fmt.Println(nextNumber())
	fmt.Println(nextNumber())
	fmt.Println(nextNumber())
	fmt.Println(nextNumber())
	fmt.Println(nextNumber())

	// ** 定义一个匿名函数并将其赋值给变量add
	add := func(x, y int) int {
		return x + y
	}
	fmt.Printf("add = %d \n", add(2, 3))

	// ** 在函数内部使用匿名函数
	multiply := func(x, y int) int {
		return x * y
	}
	product := multiply(4, 6)
	fmt.Println("multiply =", product)

	// ** 将匿名函数作为参数传递给其他函数
	calculate := func(operate func(x, y int) int, x, y int) int {
		return operate(x, y)
	}
	sum := calculate(add, 100, 123)
	fmt.Println("sum = ", sum)

	// ** 直接在函数调用中定义匿名函数
	diff := calculate(func(x, y int) int {
		return x - y
	}, 100, 33)
	fmt.Println("diff = ", diff)

	// 方法: 类型(结构体等)对象中的方法 (类似于Java类中的成员方法)
	var c1 Circle
	c1.radius = 10.0
	area := c1.getArea()
	fmt.Println("圆的面积：", area)

	numbers := []int{1, 2, 3, 4, 5, 6}
	printSlice(numbers)

	numbers1 := make([]int, 0, 5)
	printSlice(numbers1)

	// 局部变量和全局变量：全局变量和局部变量可以重名定义，函数内优先考虑局部变量
	var globalOrLocalVar int = 99
	fmt.Println(globalOrLocalVar)
}

func printSlice(x []int) {
	fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}

func max(val1, val2 int) int {
	if val1 > val2 {
		return val1
	} else {
		return val2
	}
}

func swap_str(x, y string) (string, string) {
	return y, x
}

func swap_val(x, y int) {
	var temp = x
	x = y
	y = temp
}

func swap_ref(x *int, y *int) {
	var temp = *x
	*x = *y
	*y = temp
}

func call_back(x int, f func(int) int) {
	f(x)
}

func call_back_test(x int) int {
	fmt.Printf("打印值：%v \n", x)
	return x
}

func getSeq() func() int {
	i := 0
	return func() int {
		i += 1
		return i
	}
}

/* 定义结构体 */
type Circle struct {
	radius float64
}

func (c Circle) getArea() float64 {
	return 3.14 * c.radius * c.radius
}
